import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;

public class Test {
    AccessLimitControl control = new AccessLimitControl();

    public static void main(String[] args) throws Exception {
        Test test = new Test();
        test.run();

    }

    public void run() throws Exception {
        for (int i = 0; i < 10; i++) {
            Thread t = new Thread(() -> {
                try {
                    String result = control.access();
                    System.out.println("Access result: " + result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
            t.start();
        }

    }

}

// 还有一种受限资源，它需要保证同一时刻最多有N个线程能访问，比如同一时刻最多创建100个数据库连接，最多允许10个用户下载等。
// 这种限制数量的锁，如果用Lock数组来实现，就太麻烦了。
// 这种情况就可以使用Semaphore，例如，最多允许3个线程同时访问：
class AccessLimitControl {
    final Semaphore semaphore = new Semaphore(3);
    final AtomicInteger counter = new AtomicInteger(0);

    public String access() throws Exception {
        int id = counter.incrementAndGet();
        long t0 = System.currentTimeMillis();
        semaphore.acquire();          // 可能阻塞
        long t1 = System.currentTimeMillis();
        try {
            System.out.printf(">> %02d 获得许可, 等待=%d ms %n", id, t1 - t0);
            Thread.sleep(1_000);      // 模拟耗时操作
            return "OK-" + id;
        } finally {
            long t2 = System.currentTimeMillis();
            System.out.printf("<< %02d 释放许可, 耗时=%d ms %n", id, t2 - t1);
            semaphore.release();
        }
    }
}
// if (semaphore.tryAcquire(3, TimeUnit.SECONDS)) {
//     // 指定等待时间3秒内获取到许可:
//     try {
//         // TODO:
//     } finally {
//         semaphore.release();
//     }
// }